<!--
 * @Author: 秦少卫
 * @Date: 2022-09-03 19:16:55
 * @LastEditors: 秦少卫
 * @LastEditTime: 2023-07-16 12:51:11
 * @Description: 插入SVG元素
-->

<template>
  <div style="display: inline-block">
    <Dropdown transfer-class-name="fix" @on-click="insertTypeHand">
      <a href="javascript:void(0)">
        {{ $t("insertFile.insert") }}
        <Icon type="ios-arrow-down"></Icon>
      </a>
      <template #list>
        <DropdownMenu>
          <!-- 图片 -->
          <DropdownItem name="insertImg">{{ $t("insertFile.insert_picture") }}</DropdownItem>
          <!-- SVG -->
          <DropdownItem name="insertSvg">{{ $t("insertFile.insert_SVG") }}</DropdownItem>
          <!-- SVG 字符串 -->
          <DropdownItem name="insertSvgStrModal">{{ $t("insertFile.insert_SVGStr") }}</DropdownItem>
        </DropdownMenu>
      </template>
    </Dropdown>
    <!-- 插入字符串svg元素 -->
    <Modal
        v-model="state.showModal"
        :title="$t('insertFile.modal_tittle')"
        @on-ok="insertTypeHand('insertSvgStr')"
        @on-cancel="showModal = false"
    >
      <Input
          v-model="state.svgStr"
          :placeholder="$t('insertFile.insert_SVGStr_placeholder')"
          show-word-limit
          type="textarea"
      />
    </Modal>
  </div>
</template>

<script name="ImportFile" setup>
import {getImgStr, selectFiles} from "@/utils/utils";
import useSelect from "@/hooks/select";
import {v4 as uuid} from "uuid";
import axios from "axios";
import Jszip from "jszip";
import {downloadFile} from "@/utils/utils";
import { Spin } from 'view-ui-plus';

const {fabric, canvasEditor} = useSelect();
const state = reactive({
  showModal: false,
  svgStr: ""
});

let emit = defineEmits(["change"]);
const HANDLEMAP = {
  // 插入图片
  insertImg: function () {
    selectFiles({accept: "image/*", multiple: true}).then((fileList) => {
      Spin.show({
        render: (h) => h('div', '加载中'),
      });
      const orgFile = fileList[0]
      const formData = new FormData();
      formData.append("file", orgFile);
      axios.request({
        url: "http://127.0.0.1:8080/api/v1/image/cut-image",
        method: "POST",
        data: formData,
        timeout: 300000,
        responseType: "blob"
      }).then(async (res) => {
        downloadFile(res.data, '11.zip')
        // 解压
        const buffer = res.data.arrayBuffer();
        const zip = new Jszip();
        const result = await zip.loadAsync(buffer);
        const fileArr = []
        // 遍历解压后的ZIP文件
        result.forEach((relativePath, file) => {
          fileArr.push(file)
        });
        const imgArr = []
        await Promise.all(fileArr.map(async (file) => {
          // 转换为base64
          const imgData = await file.async('base64')
          imgArr.push(`data:image/jpg;base64,${imgData}`)
        }));
        console.log('图片数量', imgArr.length)
        // 设置画布宽高为图片的宽高
        const {width: imgWidth,height: imgHeight} = await getImageSize(URL.createObjectURL(orgFile))
        emit("sizeChange", {width: imgWidth, height: imgHeight});
        canvasEditor.setSize(imgWidth, imgHeight);
        // 第一步，找出背景图，背景图：宽度高度都等于原图片高度宽度
        await Promise.all(imgArr.map(async (img, index) => {
          const {width, height} = await clearBlankImg(img)
          // console.log('背景图：', index, width,imgWidth , height , imgHeight)
          if(imgWidth - width <=1 && imgHeight- height <=1){
            imgArr.splice(index, 1)
            return true
          }
        }))
        // 第二步，找出重叠的部分删除，只保留最完整的那张
        const tempImgArr = [...imgArr]
        for (let i = tempImgArr.length - 1; i >= 0; i--) {
          for (let j = imgArr.length - 1; j >= 0; j--) {
            const img1 = await clearBlankImg(tempImgArr[i])
            const img2 = await clearBlankImg(imgArr[j])
            // 1包含了2，有可能误差1像素
            if(img2.top+1 >= img1.top && img2.left >= img1.left && img2.bottom <= img1.bottom && img2.right <= img1.right){
              // 判断
              const { width: img1Width, height: img1Height} = await  getImageSize(img1.img)
              const { width: img2Width, height: img2Height} = await  getImageSize(img2.img)
              // console.log('====', img1Width, img2Width, img1Height, img2Height)
              if(img1Width> img2Width || img1Height> img2Height){
                imgArr.splice(j, 1)
              }
            }
          }
        }
        console.log('剩余图片：', imgArr.length)
        imgArr.map(async (base64) => {
          clearBlankImg(base64).then((res) => {
            insertImgFile(res.img, res.left, res.top);
          });
        })
        Spin.hide()
      });
    });
  },
  // 插入Svg
  insertSvg: function () {
    selectFiles({accept: ".svg", multiple: true}).then((fileList) => {
      Array.from(fileList).forEach((item) => {
        getImgStr(item).then((file) => {
          insertSvgFile(file);
        });
      });
    });
  },
  // 插入SVG元素
  insertSvgStrModal: function () {
    state.svgStr = "";
    state.showModal = true;
  },
  // 插入字符串元素
  insertSvgStr: function () {
    fabric.loadSVGFromString(state.svgStr, (objects, options) => {
      const item = fabric.util.groupSVGElements(objects, {
        ...options,
        name: "defaultSVG",
        id: uuid()
      });
      canvasEditor.canvas.add(item).centerObject(item).renderAll();
    });
  }
};

const insertTypeHand = (type) => {
  const cb = HANDLEMAP[type];
  cb && typeof cb === "function" && cb();
};

// 插入图片文件
function insertImgFile(file, left, top) {
  if (!file) throw new Error("file is undefined");
  const imgEl = document.createElement("img");
  imgEl.src = file;
  // 插入页面
  document.body.appendChild(imgEl);
  imgEl.onload = () => {
    // 创建图片对象
    const imgInstance = new fabric.Image(imgEl, {
      id: uuid(),
      name: "图片1",
      left: left || 100,
      top: top || 100
    });
    // 设置缩放
    canvasEditor.canvas.add(imgInstance);
    canvasEditor.canvas.setActiveObject(imgInstance);
    canvasEditor.canvas.renderAll();
    // 删除页面中的图片元素
    imgEl.remove();
  };
}

// 插入文件元素
function insertSvgFile(svgFile) {
  if (!svgFile) throw new Error("file is undefined");
  fabric.loadSVGFromURL(svgFile, (objects, options) => {
    const item = fabric.util.groupSVGElements(objects, {
      ...options,
      name: "defaultSVG",
      id: uuid()
    });
    canvasEditor.canvas.add(item).centerObject(item).renderAll();
  });
}

function getImageSize(imgData) {
  return new Promise((resolve) => {
    var img = new Image(); //创建图片对象
    img.src = imgData;
    img.onload = function () {
      resolve({
        width: img.width,
        height: img.height
      });
    };
  });
}

function clearBlankImg(imgData) {
  return new Promise((resolve) => {
    const img = new Image(); //创建图片对象
    img.src = imgData;
    img.onload = function () {
      const c = document.createElement("canvas"); //创建处理画布对象
      const ctx = c.getContext("2d");
      c.width = img.width;
      c.height = img.height;
      ctx.drawImage(img, 0, 0); //绘制
      const imgData = ctx.getImageData(0, 0, c.width, c.height).data; //读取图片数据
      let lOffset = c.width,
          rOffset = 0,
          tOffset = c.height,
          bOffset = 0;
      for (let i = 0; i < c.width; i++) {
        for (let j = 0; j < c.height; j++) {
          const pos = (i + c.width * j) * 4;
          if (
              imgData[pos] === 255 ||
              imgData[pos + 1] === 255 ||
              imgData[pos + 2] === 255 ||
              imgData[pos + 3] === 255
          ) {
            bOffset = Math.max(j, bOffset); // 找到有色彩的最下端
            rOffset = Math.max(i, rOffset); // 找到有色彩的最右端
            tOffset = Math.min(j, tOffset); // 找到有色彩的最上端
            lOffset = Math.min(i, lOffset); // 找到有色彩的最左端
          }
        }
      }
      lOffset++;
      rOffset++;
      tOffset++;
      bOffset++;
      var x = document.createElement("canvas"); //创建处理后画布对象
      x.width = rOffset - lOffset;
      x.height = bOffset - tOffset;
      var xx = x.getContext("2d");
      xx.drawImage(img, lOffset, tOffset, x.width, x.height, 0, 0, x.width, x.height); //绘制
      // 得到最终裁剪出来的base64
      resolve({
        img: x.toDataURL(),
        left: lOffset,
        top: tOffset,
        right: rOffset,
        bottom: bOffset,
        width: x.width,
        height: x.height
      });
    };
  });
}

function loadImageToCanvas(imgData) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = function () {
      const canvas = document.createElement("canvas");
      const ctx = canvas.getContext('2d');
      ctx.width = img.width;
      ctx.height = img.height;
      ctx.drawImage(img, 0, 0);
      resolve(ctx)
    };
    img.onerror = reject;
    img.src = imgData;
  });
}

// 检查两个图像的不透明区域是否有重叠
async function checkOverlap(img1, img2) {
  const ctx1 = await loadImageToCanvas(img1)
  const ctx2 = await loadImageToCanvas(img2)
  const imgData1 = ctx1.getImageData(0, 0, ctx1.width, ctx1.height).data;
  const imgData2 = ctx2.getImageData(0, 0, ctx2.width, ctx2.height).data;

  for (let i = 0; i < imgData1.length; i += 4) {
    if (imgData1[i + 3] !== 0 && imgData2[i + 3] !== 0) {
      return true; // 两个图像在该处均不透明，表示重叠
    }
  }
  return false; // 没有重叠
}

</script>

<style lang="less" scoped>
:deep(.ivu-select-dropdown) {
  z-index: 999;
}
</style>
